// // ******************************************************************
// //       /\ /|       @file       AudioSubtitleHelper.cs
// //       \ V/        @brief      await29
// //       | "")       @author     Await, 285283010@qq.com
// //       /  |
// //      /  \\        @Modified   2025-03-02 16:03
// //    *(__\_\        @Copyright  Copyright (c) , 2025-02-23 10:02 Await
// // ******************************************************************

using System;
using System.IO;
using System.Threading.Tasks;
using System.Text;
using System.Collections.Generic;
using Xabe.FFmpeg;
using Whisper.net;
using Whisper.net.Ggml;
using System.Linq;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using Microsoft.Extensions.Logging;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security.Cryptography;
using AutomaticSubtitles.Service.Domain.Filter;
using AutomaticSubtitles.Service.Infrastructure.Helper;

namespace AutomaticSubtitles.Service.Infrastructure.Helper;

public class AudioSubtitleHelper
{
    private const string MODEL_FOLDER_NAME = "WhisperModels";
    private const string TEMP_FOLDER_NAME = "SubtitleExtracted";
    private static readonly string DEFAULT_MODEL_PATH = Path.Combine(Common.GlobalPath, MODEL_FOLDER_NAME, "ggml-base.bin");
    private static readonly SemaphoreSlim _modelLock = new(1, 1);
    private static readonly ILogger _logger = LoggingHelper.GetLogger(typeof(AudioSubtitleHelper).FullName);

    /// <summary>
    /// 从音频流提取字幕
    /// </summary>
    /// <param name="audioStream">音频流</param>
    /// <param name="outputFilePath">临时文件输出路径</param>
    /// <param name="options">Whisper配置选项</param>
    /// <param name="progress">进度报告回调</param>
    /// <param name="mediaName">媒体名称，用于创建分类目录</param>
    /// <returns>字幕结果信息</returns>
    public static async Task<SubtitleResult> ExtractSubtitleFromAudioAsync(
        IAudioStream audioStream,
        string outputFilePath,
        WhisperOptions options = null,
        IProgress<ProcessProgress> progress = null,
        string mediaName = null)
    {
        options ??= new WhisperOptions();
        var result = new SubtitleResult();

        try
        {
            // 确保模型目录存在
            progress?.Report(new ProcessProgress { Stage = "初始化", Percentage = 0, Details = "创建必要目录" });
            var modelDirectory = Path.GetDirectoryName(options.ModelPath);
            if (!Directory.Exists(modelDirectory)) Directory.CreateDirectory(modelDirectory);

            // 创建临时文件基础目录结构
            var baseTempDir = Path.Combine(Common.GlobalPath, TEMP_FOLDER_NAME);
            if (!Directory.Exists(baseTempDir)) Directory.CreateDirectory(baseTempDir);

            // 按类型分类存储
            var tempDirType = Path.Combine(baseTempDir, "temp");
            if (!Directory.Exists(tempDirType)) Directory.CreateDirectory(tempDirType);

            var wavDirType = Path.Combine(baseTempDir, "wav");
            if (!Directory.Exists(wavDirType)) Directory.CreateDirectory(wavDirType);

            var outputDirType = Path.Combine(baseTempDir, "output");
            if (!Directory.Exists(outputDirType)) Directory.CreateDirectory(outputDirType);

            // 确保输出目录存在 (原始请求的输出目录，仅用于最终输出)
            var clientOutputDirectory = Path.GetDirectoryName(outputFilePath);
            if (!Directory.Exists(clientOutputDirectory)) Directory.CreateDirectory(clientOutputDirectory);

            // 创建媒体特定子目录（如果提供了媒体名称）
            var mediaFolder = "unknown";
            if (!string.IsNullOrEmpty(mediaName))
            {
                // 清理媒体名称，移除无效字符
                mediaFolder = string.Join("_", mediaName.Split(Path.GetInvalidFileNameChars()));
                // 限制长度
                if (mediaFolder.Length > 50) mediaFolder = mediaFolder.Substring(0, 50);
            }

            // 计算音频流的哈希码作为唯一标识符
            var fileHash = CalculateAudioStreamHashAsync(audioStream);
            _logger.LogInformation($"音频流哈希码: {fileHash}");

            // 使用哈希码创建目录和文件名
            var mediaTempDir = Path.Combine(tempDirType, mediaFolder, fileHash);
            if (!Directory.Exists(mediaTempDir)) Directory.CreateDirectory(mediaTempDir);

            // 临时字幕文件路径（最终结果）
            var srtFileName = $"{mediaFolder}.{fileHash}.srt";
            var srtFilePath = Path.Combine(outputDirType, srtFileName);

            // 检查是否已经存在处理结果
            if (File.Exists(srtFilePath) && new FileInfo(srtFilePath).Length > 0)
            {
                _logger.LogInformation($"发现已处理的字幕文件: {srtFilePath}，直接使用");
                result.SubtitlePath = srtFilePath;

                // 尝试从文件名或内容推断语言
                try
                {
                    // 读取SRT文件的前几行，尝试识别语言
                    var srtContent = await File.ReadAllTextAsync(srtFilePath);
                    result.DetectedLanguage = InferLanguageFromSrtContent(srtContent);
                    result.SegmentCount = CountSegmentsInSrt(srtContent);
                    _logger.LogInformation($"从已存在文件中推断语言: {result.DetectedLanguage}, 段落数: {result.SegmentCount}");

                    progress?.Report(new ProcessProgress { Stage = "完成", Percentage = 100, Details = "使用已存在的字幕文件" });
                    return result;
                }
                catch (Exception ex)
                {
                    _logger.LogWarning($"读取已存在字幕文件时出错: {ex.Message}，将重新处理");
                }
            }

            // 临时WAV文件路径
            var wavFileName = $"{mediaFolder}_{fileHash}.wav";
            var wavFilePath = Path.Combine(wavDirType, wavFileName);
            _logger.LogInformation($"尝试提取音频数据: {wavFileName}");

            // 临时中间WAV文件路径 (FFmpeg转换的初始WAV文件)
            var tempWavFileName = $"{mediaFolder}_{fileHash}_temp.wav";
            var tempWavFilePath = Path.Combine(wavDirType, tempWavFileName);

            // 设置结果路径
            result.SubtitlePath = srtFilePath;

            try
            {
                // 获取源音频采样率
                progress?.Report(new ProcessProgress { Stage = "音频转换", Percentage = 10, Details = "检查音频采样率" });
                var sourceSampleRate = audioStream.SampleRate;
                var needsResampling = sourceSampleRate != 16000;

                progress?.Report(new ProcessProgress
                {
                    Stage = "音频转换",
                    Percentage = 15,
                    Details = $"源音频采样率: {sourceSampleRate}Hz, {(needsResampling ? "需要高质量重采样" : "无需重采样")}"
                });

                // 步骤1: 使用FFmpeg将音频转换为WAV格式(但保留原采样率)
                progress?.Report(new ProcessProgress
                {
                    Stage = "音频转换",
                    Percentage = 20,
                    Details = "转换为WAV格式"
                });

                // 设置音频编码为PCM
                audioStream.SetCodec("pcm_s16le");

                var conversion = FFmpeg.Conversions.New()
                    .AddStream(audioStream)
                    .SetOutput(tempWavFilePath);

                await conversion.Start();

                progress?.Report(new ProcessProgress
                {
                    Stage = "音频转换",
                    Percentage = 25,
                    Details = "WAV格式转换完成，准备重采样"
                });

                // 步骤2: 使用NAudio进行高质量重采样
                if (needsResampling)
                {
                    progress?.Report(new ProcessProgress
                    {
                        Stage = "音频转换",
                        Percentage = 30,
                        Details = "使用NAudio进行高质量重采样"
                    });

                    await ResampleWavFileWithNAudioAsync(tempWavFilePath, wavFilePath, 16000);

                    progress?.Report(new ProcessProgress
                    {
                        Stage = "音频转换",
                        Percentage = 35,
                        Details = "重采样完成"
                    });
                }
                else
                {
                    // 如果不需要重采样，直接使用临时WAV文件
                    File.Copy(tempWavFilePath, wavFilePath, true);
                }

                // 验证生成的WAV文件采样率
                var wavInfo = await FFmpeg.GetMediaInfo(wavFilePath);
                var wavAudioStream = wavInfo.AudioStreams.FirstOrDefault();
                if (wavAudioStream != null && wavAudioStream.SampleRate != 16000) throw new Exception($"音频采样率转换失败，当前采样率为{wavAudioStream.SampleRate}，但Whisper需要16000Hz");

                // 使用Whisper进行语音识别
                await _modelLock.WaitAsync();
                try
                {
                    // 检查模型文件是否存在，不存在则下载
                    if (!File.Exists(options.ModelPath))
                    {
                        progress?.Report(new ProcessProgress { Stage = "模型准备", Percentage = 40, Details = "下载Whisper模型" });
                        await DownloadModelAsync(options.ModelType, options.ModelPath);
                    }

                    progress?.Report(new ProcessProgress { Stage = "语音识别", Percentage = 45, Details = "初始化Whisper模型" });
                    using var whisperFactory = await InitWhisperFactory(options.ModelPath, progress);

                    // 创建处理器
                    using var processor = whisperFactory.CreateBuilder()
                        .WithLanguage(options.Language)
                        .Build();

                    // 处理音频文件
                    progress?.Report(new ProcessProgress { Stage = "语音识别", Percentage = 50, Details = "开始处理音频" });
                    var segments = new List<(TimeSpan Start, TimeSpan End, string Text)>();
                    await using (var audioFileStream = File.OpenRead(wavFilePath))
                    {
                        var segmentCount = 0;
                        try
                        {
                            // 记录检测到的语言
                            var detectedLanguage = "auto";
                            var sumLen = audioFileStream.Length;

                            await foreach (var segment in processor.ProcessAsync(audioFileStream))
                            {
                                // 如果是第一个片段，尝试获取语言
                                if (segmentCount == 0 && !string.IsNullOrEmpty(segment.Language))
                                {
                                    detectedLanguage = segment.Language;
                                    result.DetectedLanguage = detectedLanguage;
                                    progress?.Report(new ProcessProgress
                                    {
                                        Stage = "语音识别",
                                        Percentage = 52,
                                        Details = $"检测到语言: {detectedLanguage}"
                                    });
                                }

                                // 检查是否包含需要过滤的词语(不直接解析仓储)
                                bool shouldFilter = await WordFilterHelper.ShouldFilterTextSimpleAsync(segment.Text, detectedLanguage);
                                if (shouldFilter)
                                {
                                    _logger.LogInformation($"片段文本已被过滤: '{segment.Text}'");
                                    continue; // 跳过这个片段，不添加到结果中
                                }

                                // 过滤掉过短的片段
                                if ((segment.End - segment.Start).TotalMilliseconds >= options.MinimumSegmentLength)
                                {
                                    segments.Add((segment.Start, segment.End, segment.Text));
                                    segmentCount++;
                                    progress?.Report(new ProcessProgress
                                    {
                                        Stage = "语音识别",
                                        Percentage = 50 + segmentCount * 30.0 / Math.Max(segments.Count, 1),
                                        Details = $"已处理 {segmentCount} 个片段，内容: {segment.Text}"
                                    });
                                }
                            }

                            result.SegmentCount = segmentCount;

                            // 设置语言，如果未检测到则使用配置的选项
                            if (result.DetectedLanguage == null) result.DetectedLanguage = options.Language != "auto" ? options.Language : detectedLanguage;
                        }
                        catch (Exception ex)
                        {
                            progress?.Report(new ProcessProgress
                            {
                                Stage = "语音识别",
                                Percentage = 60,
                                Details = $"处理过程中出现错误: {ex.Message}"
                            });

                            // 重新抛出异常，但已记录在日志中
                            throw new Exception($"音频处理失败: {ex.Message}", ex);
                        }
                    }

                    // 如果没有提取到足够的片段，抛出异常
                    if (segments.Count < 1) throw new Exception("未能从音频中提取到足够的字幕片段，可能是音频质量问题或不包含语音内容");

                    // 生成SRT格式字幕
                    progress?.Report(new ProcessProgress { Stage = "生成字幕", Percentage = 90, Details = "生成SRT文件" });
                    await GenerateSrtFileAsync(segments, srtFilePath);
                    progress?.Report(new ProcessProgress { Stage = "完成", Percentage = 100, Details = "字幕生成完成" });
                }
                finally
                {
                    _modelLock.Release();
                }

                return result;
            }
            finally
            {
                // 清理临时文件
                try
                {
                    if (!options.KeepWavFile && File.Exists(wavFilePath))
                        File.Delete(wavFilePath);

                    if (File.Exists(tempWavFilePath))
                        File.Delete(tempWavFilePath);
                }
                catch (Exception ex)
                {
                    // 记录但不抛出异常
                    _logger.LogError(ex, $"清理临时文件时发生错误: {ex.Message}");
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception($"从音频提取字幕时发生错误: {ex.Message}", ex);
        }
    }

    /// <summary>
    /// 使用NAudio库对WAV文件进行高质量重采样
    /// </summary>
    /// <param name="inputWavPath">输入WAV文件路径</param>
    /// <param name="outputWavPath">输出WAV文件路径</param>
    /// <param name="targetSampleRate">目标采样率(Hz)</param>
    /// <returns>异步任务</returns>
    private static async Task ResampleWavFileWithNAudioAsync(string inputWavPath, string outputWavPath, int targetSampleRate)
    {
        try
        {
            // 使用Task.Run将同步操作包装为异步操作
            await Task.Run(() =>
            {
                _logger.LogInformation($"开始使用NAudio重采样: 输入={inputWavPath}, 输出={outputWavPath}, 目标采样率={targetSampleRate}Hz");

                // 获取输入文件的信息用于日志记录
                var inputWavInfo = string.Empty;
                try
                {
                    using (var reader = new WaveFileReader(inputWavPath))
                    {
                        inputWavInfo = $"通道数: {reader.WaveFormat.Channels}, 采样率: {reader.WaveFormat.SampleRate}Hz, 位深: {reader.WaveFormat.BitsPerSample}位";
                        _logger.LogInformation($"输入WAV文件信息: {inputWavInfo}");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"读取输入WAV文件信息时出错: {ex.Message}");
                }

                using (var fileStream = File.OpenRead(inputWavPath))
                using (var reader = new WaveFileReader(fileStream))
                using (var outFileStream = File.Create(outputWavPath))
                {
                    // 使用WdlResamplingSampleProvider进行高质量重采样
                    var resampler = new WdlResamplingSampleProvider(reader.ToSampleProvider(), targetSampleRate);
                    _logger.LogInformation($"已创建WdlResamplingSampleProvider重采样器");

                    // 将重采样后的音频写入输出文件
                    WaveFileWriter.WriteWavFileToStream(outFileStream, resampler.ToWaveProvider16());
                    _logger.LogInformation($"重采样完成并写入文件: {outputWavPath}");
                }

                // 验证输出文件
                try
                {
                    using (var reader = new WaveFileReader(outputWavPath))
                    {
                        var outputWavInfo = $"通道数: {reader.WaveFormat.Channels}, 采样率: {reader.WaveFormat.SampleRate}Hz, 位深: {reader.WaveFormat.BitsPerSample}位";
                        _logger.LogInformation($"输出WAV文件信息: {outputWavInfo}");

                        if (reader.WaveFormat.SampleRate != targetSampleRate)
                            _logger.LogWarning($"警告: 输出WAV文件采样率 ({reader.WaveFormat.SampleRate}Hz) 与目标采样率 ({targetSampleRate}Hz) 不一致");
                        else
                            _logger.LogInformation($"成功: 输出WAV文件采样率验证通过 ({reader.WaveFormat.SampleRate}Hz)");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"验证输出WAV文件时出错: {ex.Message}");
                }
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"NAudio重采样过程中发生错误: {ex.Message}");
            throw new Exception($"NAudio重采样失败: {ex.Message}", ex);
        }
    }

    /// <summary>
    /// 下载Whisper模型
    /// </summary>
    private static async Task DownloadModelAsync(GgmlType modelType, string modelPath)
    {
        using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(modelType);
        using var fileWriter = File.OpenWrite(modelPath);
        await modelStream.CopyToAsync(fileWriter);
    }

    /// <summary>
    /// 生成SRT格式字幕文件
    /// </summary>
    private static async Task GenerateSrtFileAsync(List<(TimeSpan Start, TimeSpan End, string Text)> segments, string srtFilePath)
    {
        var srtContent = new StringBuilder();
        var index = 1;

        foreach (var segment in segments)
        {
            srtContent.AppendLine(index.ToString());
            srtContent.AppendLine($"{FormatTimeSpan(segment.Start)} --> {FormatTimeSpan(segment.End)}");
            srtContent.AppendLine(segment.Text.Trim());
            srtContent.AppendLine();
            index++;
        }

        await File.WriteAllTextAsync(srtFilePath, srtContent.ToString(), Encoding.UTF8);
    }

    /// <summary>
    /// 格式化时间戳为SRT格式
    /// </summary>
    private static string FormatTimeSpan(TimeSpan time)
    {
        return $"{(int)time.TotalHours:00}:{time.Minutes:00}:{time.Seconds:00},{time.Milliseconds:000}";
    }

    /// <summary>
    /// 清理过期的临时文件
    /// </summary>
    /// <param name="maxAgeHours">文件最大保留时间（小时），默认48小时</param>
    /// <param name="cleanFinalDir">是否清理final目录中的文件，默认false</param>
    /// <returns>清理的文件数量</returns>
    public static int CleanupTempFiles(int maxAgeHours = 48, bool cleanFinalDir = false)
    {
        var deletedCount = 0;
        try
        {
            var baseTempDir = Path.Combine(Common.GlobalPath, TEMP_FOLDER_NAME);
            if (!Directory.Exists(baseTempDir))
                return 0;

            // 获取截止时间
            var cutoffTime = DateTime.Now.AddHours(-maxAgeHours);
            _logger.LogInformation($"清理临时文件：保留期 {maxAgeHours} 小时，截止时间 {cutoffTime}");

            // 清理临时WAV文件
            var wavDir = Path.Combine(baseTempDir, "wav");
            if (Directory.Exists(wavDir))
                foreach (var file in Directory.GetFiles(wavDir, "*.*", SearchOption.AllDirectories))
                    if (File.GetLastWriteTime(file) < cutoffTime)
                        try
                        {
                            File.Delete(file);
                            deletedCount++;
                        }
                        catch (Exception ex)
                        {
                            // 记录错误，继续处理其他文件
                            _logger.LogError(ex, $"清理WAV文件时出错: {ex.Message}, 文件: {file}");
                        }

            // 清理临时处理目录中的文件
            var tempDir = Path.Combine(baseTempDir, "temp");
            if (Directory.Exists(tempDir))
            {
                foreach (var file in Directory.GetFiles(tempDir, "*.*", SearchOption.AllDirectories))
                    if (File.GetLastWriteTime(file) < cutoffTime)
                        try
                        {
                            File.Delete(file);
                            deletedCount++;
                        }
                        catch (Exception ex)
                        {
                            // 记录错误，继续处理其他文件
                            _logger.LogError(ex, $"清理临时文件时出错: {ex.Message}, 文件: {file}");
                        }

                // 清理空目录
                foreach (var dir in Directory.GetDirectories(tempDir, "*", SearchOption.AllDirectories)
                             .OrderByDescending(d => d.Length)) // 从最深层目录开始
                    try
                    {
                        if (!Directory.EnumerateFileSystemEntries(dir).Any()) Directory.Delete(dir);
                    }
                    catch (Exception ex)
                    {
                        // 记录错误，继续处理其他目录
                        _logger.LogError(ex, $"清理空目录时出错: {ex.Message}, 目录: {dir}");
                    }
            }

            // 清理output目录中的文件
            var outputDir = Path.Combine(baseTempDir, "output");
            if (Directory.Exists(outputDir))
                foreach (var file in Directory.GetFiles(outputDir, "*.*", SearchOption.AllDirectories))
                    if (File.GetLastWriteTime(file) < cutoffTime)
                        try
                        {
                            File.Delete(file);
                            deletedCount++;
                        }
                        catch (Exception ex)
                        {
                            // 记录错误，继续处理其他文件
                            _logger.LogError(ex, $"清理输出文件时出错: {ex.Message}, 文件: {file}");
                        }

            // 清理final目录中的文件（如果启用）
            if (cleanFinalDir)
            {
                var finalDir = Path.Combine(baseTempDir, "final");
                if (Directory.Exists(finalDir))
                {
                    foreach (var file in Directory.GetFiles(finalDir, "*.*", SearchOption.AllDirectories))
                        if (File.GetLastWriteTime(file) < cutoffTime)
                            try
                            {
                                File.Delete(file);
                                deletedCount++;
                            }
                            catch (Exception ex)
                            {
                                // 记录错误，继续处理其他文件
                                _logger.LogError(ex, $"清理final目录文件时出错: {ex.Message}, 文件: {file}");
                            }

                    // 清理空目录
                    foreach (var dir in Directory.GetDirectories(finalDir, "*", SearchOption.AllDirectories)
                                 .OrderByDescending(d => d.Length)) // 从最深层目录开始
                        try
                        {
                            if (!Directory.EnumerateFileSystemEntries(dir).Any()) Directory.Delete(dir);
                        }
                        catch (Exception ex)
                        {
                            // 记录错误，继续处理其他目录
                            _logger.LogError(ex, $"清理final空目录时出错: {ex.Message}, 目录: {dir}");
                        }
                }
            }

            _logger.LogInformation($"临时文件清理完成，共删除 {deletedCount} 个文件");
            return deletedCount;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"清理临时文件过程中发生错误: {ex.Message}");
            return deletedCount;
        }
    }

    /// <summary>
    /// 初始化Whisper工厂，负责加载模型并创建Whisper实例
    /// </summary>
    private static async Task<WhisperFactory> InitWhisperFactory(string modelPath, IProgress<ProcessProgress> progress)
    {
        _logger.LogInformation($"初始化Whisper工厂，模型路径: {modelPath}");
        progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 0, Details = "检查模型文件..." });

        // 确保模型文件存在
        if (!File.Exists(modelPath))
        {
            _logger.LogWarning($"模型文件不存在: {modelPath}，将尝试下载");
            progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 5, Details = "模型文件不存在，准备下载..." });
        }
        else
        {
            _logger.LogInformation($"模型文件存在: {modelPath}, 大小: {new FileInfo(modelPath).Length / 1024 / 1024} MB");
            progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 10, Details = "模型文件已存在，准备加载..." });
        }

        // 确保Whisper运行时库已加载
        EnsureWhisperRuntimeLoaded();
        progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 20, Details = "运行时库检查完成" });

        // 记录当前平台信息
        var platform = string.Empty;
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            platform = "Windows";
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            platform = "Linux";
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            platform = "macOS";

        var architecture = RuntimeInformation.ProcessArchitecture.ToString();
        _logger.LogInformation($"当前运行平台: {platform} {architecture}, OS描述: {RuntimeInformation.OSDescription}");
        progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 30, Details = $"在{platform}平台上初始化..." });

        try
        {
            // 标准初始化尝试
            _logger.LogInformation("尝试标准初始化WhisperFactory");

            // 创建平台特定的选项
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                // 检查Linux环境下的库文件位置
                var assemblyLocation = Assembly.GetExecutingAssembly().Location;
                var assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
                var runtimePath = Path.Combine(assemblyDirectory, "runtimes", "linux-x64", "native");

                if (Directory.Exists(runtimePath))
                {
                    var libFiles = Directory.GetFiles(runtimePath, "libwhisper.*");
                    _logger.LogInformation($"Linux环境: 库文件路径检查: {runtimePath}, 找到 {libFiles.Length} 个匹配文件");
                }
                else
                {
                    _logger.LogWarning($"Linux环境: 库目录不存在: {runtimePath}");
                }
            }

            progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 50, Details = "创建Whisper工厂实例..." });

            // 创建WhisperFactory实例
            var factory = WhisperFactory.FromPath(modelPath);
            progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 90, Details = "Whisper工厂初始化成功" });
            _logger.LogInformation("Whisper模型初始化成功");
            return factory;
        }
        catch (Exception ex)
        {
            // 详细记录异常信息，包括平台和架构
            var errorMsg = $"初始化Whisper模型失败: {ex.Message} (平台: {platform} {architecture})";
            _logger.LogError(ex, errorMsg);

            if (ex.Message.Contains("Failed to load native whisper library") ||
                ex.InnerException?.Message?.Contains("Failed to load native whisper library") == true)
            {
                // 提供特定于库加载错误的详细信息
                _logger.LogError("无法加载Whisper原生库，这通常是由于找不到必要的库文件或其依赖项");

                // 为Linux环境提供更具体的故障排除建议
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    _logger.LogWarning("Linux环境故障排除建议:");
                    _logger.LogWarning("1. 确保已安装必要的依赖: sudo apt-get install -y libgomp1");
                    _logger.LogWarning("2. 检查runtimes/linux-x64/native目录中是否存在libwhisper.so文件");
                    _logger.LogWarning("3. 确保libwhisper.so文件有执行权限: chmod +x libwhisper.so");
                    _logger.LogWarning("4. 设置环境变量: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/app/runtimes/linux-x64/native/");
                }
            }

            progress?.Report(new ProcessProgress { Stage = "初始化模型", Percentage = 0, Details = $"初始化失败: {ex.Message}" });
            throw new Exception($"初始化Whisper模型失败: {ex.Message} (平台: {platform} {architecture})", ex);
        }
    }

    /// <summary>
    /// 确保Whisper运行时库正确加载
    /// </summary>
    private static void EnsureWhisperRuntimeLoaded()
    {
        try
        {
            var assemblyLocation = Assembly.GetExecutingAssembly().Location;
            var assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
            _logger.LogInformation($"程序集目录: {assemblyDirectory}");

            // 获取运行时信息
            var architecture = RuntimeInformation.ProcessArchitecture.ToString().ToLower();
            var platform = string.Empty;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                platform = "win";
                // 添加DLL搜索路径
                var runtimePath = Path.Combine(assemblyDirectory, "runtimes", $"{platform}-{architecture}", "native");
                _logger.LogInformation($"Windows环境: 尝试加载来自 {runtimePath} 的Whisper运行时库");

                if (Directory.Exists(runtimePath))
                {
                    // 设置DLL搜索路径 (仅Windows平台)
                    SetDllDirectory(runtimePath);
                    _logger.LogInformation($"Windows环境: 已设置DLL搜索路径: {runtimePath}");

                    // 记录库文件是否存在（Windows环境）
                    var dllFiles = Directory.GetFiles(runtimePath, "whisper.dll");
                    foreach (var file in dllFiles) _logger.LogInformation($"Windows环境: 找到库文件: {file}");
                }
                else
                {
                    _logger.LogWarning($"Windows环境: DLL目录不存在: {runtimePath}");
                }
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                platform = "linux";
                // Linux环境下的处理方式不同于Windows
                var runtimePath = Path.Combine(assemblyDirectory, "runtimes", $"{platform}-{architecture}", "native");
                _logger.LogInformation($"Linux环境: 检测运行时目录: {runtimePath}");

                if (Directory.Exists(runtimePath))
                {
                    _logger.LogInformation($"Linux环境: 检测到Whisper.net库目录: {runtimePath}");

                    // 记录库文件是否存在（Linux环境）
                    var libFiles = Directory.GetFiles(runtimePath, "libwhisper.*");
                    if (libFiles.Length > 0)
                    {
                        foreach (var file in libFiles)
                            try
                            {
                                var fileInfo = new FileInfo(file);
                                _logger.LogInformation($"Linux环境: 找到库文件: {file}, 大小: {fileInfo.Length} 字节, 权限: {fileInfo.Attributes}");
                            }
                            catch (Exception ex)
                            {
                                _logger.LogWarning($"Linux环境: 检查文件信息时出错: {ex.Message}");
                            }
                    }
                    else
                    {
                        _logger.LogWarning($"Linux环境: 在目录 {runtimePath} 中未找到libwhisper.*文件");

                        // 列出所有存在的文件
                        var allFiles = Directory.GetFiles(runtimePath);
                        if (allFiles.Length > 0)
                        {
                            _logger.LogInformation($"Linux环境: 目录中存在 {allFiles.Length} 个文件:");
                            foreach (var file in allFiles) _logger.LogInformation($"Linux环境: 文件: {Path.GetFileName(file)}");
                        }
                        else
                        {
                            _logger.LogWarning($"Linux环境: 目录 {runtimePath} 为空");
                        }
                    }

                    // 检查系统库目录
                    if (File.Exists("/usr/lib/libwhisper.so") || File.Exists("/usr/lib/x86_64-linux-gnu/libwhisper.so")) _logger.LogInformation("Linux环境: 在系统库目录中找到libwhisper.so");

                    // 记录环境变量
                    _logger.LogInformation($"Linux环境: 当前LD_LIBRARY_PATH: {Environment.GetEnvironmentVariable("LD_LIBRARY_PATH")}");
                }
                else
                {
                    _logger.LogWarning($"Linux环境: 库目录不存在: {runtimePath}");

                    // 检查上级目录结构
                    var runtimesDir = Path.Combine(assemblyDirectory, "runtimes");
                    if (Directory.Exists(runtimesDir))
                    {
                        var subDirs = Directory.GetDirectories(runtimesDir);
                        _logger.LogInformation($"Linux环境: runtimes目录包含以下子目录: {string.Join(", ", subDirs.Select(Path.GetFileName))}");
                    }
                    else
                    {
                        _logger.LogWarning($"Linux环境: runtimes目录不存在: {runtimesDir}");
                    }
                }

                // 提供故障排除建议
                _logger.LogInformation("Linux环境: 故障排除建议:");
                _logger.LogInformation("1. 确保已安装必要的依赖: sudo apt-get install -y libgomp1");
                _logger.LogInformation("2. 检查runtimes/linux-x64/native目录中是否存在libwhisper.so文件");
                _logger.LogInformation("3. 确保libwhisper.so文件有执行权限: chmod +x libwhisper.so");
                _logger.LogInformation("4. 考虑设置LD_LIBRARY_PATH环境变量指向包含libwhisper.so的目录");
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                platform = "osx";
                _logger.LogInformation($"MacOS环境: Whisper.net库路径可能为: runtimes/{platform}-{architecture}/native");
            }

            _logger.LogInformation($"当前运行平台: {platform}-{architecture}, OS描述: {RuntimeInformation.OSDescription}");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "确保Whisper运行时库加载时出错");
        }
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetDllDirectory(string lpPathName);

    private static string CalculateAudioStreamHashAsync(IAudioStream audioStream)
    {
        try
        {
            // 使用音频流的基本属性创建唯一标识符
            var hashInput = new StringBuilder();

            // 使用可用的音频属性
            hashInput.Append(audioStream.SampleRate);
            hashInput.Append(audioStream.Channels);

            // 尝试获取更多属性（如果可用）
            try
            {
                if (audioStream.GetType().GetProperty("Duration") != null)
                {
                    var duration = audioStream.GetType().GetProperty("Duration").GetValue(audioStream);
                    if (duration != null) hashInput.Append(duration.ToString());
                }

                if (audioStream.GetType().GetProperty("Codec") != null)
                {
                    var codec = audioStream.GetType().GetProperty("Codec").GetValue(audioStream);
                    if (codec != null) hashInput.Append(codec.ToString());
                }

                if (audioStream.GetType().GetProperty("StreamIndex") != null)
                {
                    var index = audioStream.GetType().GetProperty("StreamIndex").GetValue(audioStream);
                    if (index != null) hashInput.Append(index.ToString());
                }
            }
            catch (Exception ex)
            {
                _logger.LogDebug($"获取音频流附加属性时出现非致命错误: {ex.Message}");
                // 继续处理，不中断哈希计算
            }

            // 添加日期部分以确保同一天处理相同内容时结果一致
            hashInput.Append(DateTime.Now.ToString("yyyyMMdd"));

            // 计算字符串的哈希值
            using (var sha256 = SHA256.Create())
            {
                var inputBytes = Encoding.UTF8.GetBytes(hashInput.ToString());
                var hashBytes = sha256.ComputeHash(inputBytes);
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower().Substring(0, 16);
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning($"计算音频流哈希值时出错: {ex.Message}，使用回退哈希算法");
            // 回退到简单算法
            return DateTime.Now.ToString("yyyyMMddHHmmss") + Guid.NewGuid().ToString("N").Substring(0, 4);
        }
    }

    private static string InferLanguageFromSrtContent(string srtContent)
    {
        // 从SRT内容中推断语言代码
        if (string.IsNullOrEmpty(srtContent))
            return "auto";

        // 获取前200行文本进行分析（避免分析整个大文件）
        var sampleText = string.Join("\n", srtContent.Split('\n').Take(200));
        sampleText = sampleText.ToLowerInvariant();

        // 定义语言特征字典 - 映射语言代码到检测函数和语言名称标识符
        var languageDetectors = new Dictionary<string, (Func<string, bool> CharacterCheck, HashSet<string> Identifiers)>
        {
            // 东亚语言
            { "zh", (ContainsChinese, ["zh", "chinese", "中文", "汉语", "普通话", "繁體", "简体"]) },
            { "ja", (ContainsJapanese, ["ja", "japanese", "日本語", "にほんご"]) },
            { "ko", (ContainsKorean, ["ko", "korean", "한국어", "조선말"]) },

            // 欧洲语言
            { "en", (null, ["en", "english", "eng"]) },
            { "fr", (null, ["fr", "french", "français", "francais"]) },
            { "de", (null, ["de", "german", "deutsch"]) },
            { "es", (null, ["es", "spanish", "español", "espanol"]) },
            { "it", (null, ["it", "italian", "italiano"]) },
            { "pt", (null, ["pt", "portuguese", "português", "portugues"]) },
            { "ru", (ContainsCyrillic, ["ru", "russian", "русский"]) },

            // 其他常见语言
            { "ar", (ContainsArabic, ["ar", "arabic", "العربية"]) },
            { "hi", (ContainsDevanagari, ["hi", "hindi", "हिन्दी"]) },
            { "th", (ContainsThai, ["th", "thai", "ไทย"]) },
            { "vi", (null, ["vi", "vietnamese", "tiếng việt"]) },
            { "nl", (null, ["nl", "dutch", "nederlands"]) },
            { "sv", (null, ["sv", "swedish", "svenska"]) },
            { "tr", (null, ["tr", "turkish", "türkçe", "turkce"]) },
            { "pl", (null, ["pl", "polish", "polski"]) },
            { "cs", (null, ["cs", "czech", "čeština", "cestina"]) },
            { "hu", (null, ["hu", "hungarian", "magyar"]) },
            { "fi", (null, ["fi", "finnish", "suomi"]) },
            { "uk", (ContainsCyrillic, ["uk", "ukrainian", "українська", "украинский"]) },
            { "fa", (ContainsPersian, ["fa", "persian", "farsi", "فارسی"]) }
        };

        // 1. 首先检查是否有明确的语言标识符
        foreach (var language in languageDetectors)
            foreach (var identifier in language.Value.Identifiers)
                // 查找完整的标识符，如语言代码和名称
                if (sampleText.Contains(identifier))
                {
                    _logger.LogDebug($"在字幕中发现语言标识符: {identifier}，推断语言为: {language.Key}");
                    return language.Key;
                }

        // 2. 如果没有找到标识符，检查字符集特征
        foreach (var language in languageDetectors)
            if (language.Value.CharacterCheck != null && language.Value.CharacterCheck(sampleText))
            {
                _logger.LogDebug($"通过字符集特征识别语言为: {language.Key}");
                return language.Key;
            }

        // 3. 进行更详细的统计分析，检查特定字符的比例
        var languageScores = CalculateLanguageScores(sampleText);
        if (languageScores.Any() && languageScores.First().Value > 0.1) // 至少10%的特征字符
        {
            var detectedLang = languageScores.OrderByDescending(x => x.Value).First().Key;
            _logger.LogDebug($"通过统计分析检测到语言: {detectedLang}，得分: {languageScores[detectedLang]:P2}");
            return detectedLang;
        }

        // 默认返回auto
        _logger.LogDebug("无法确定语言，返回auto");
        return "auto";
    }

    /// <summary>
    /// 检查文本中是否包含中文字符
    /// </summary>
    private static bool ContainsChinese(string text)
    {
        // CJK统一汉字 (中日韩) - 主要汉字范围
        return text.Any(c =>
                (c >= 0x4E00 && c <= 0x9FFF) || // CJK统一汉字
                (c >= 0x3400 && c <= 0x4DBF) || // CJK扩展A
                (c >= 0x20000 && c <= 0x2A6DF)  // CJK扩展B
        );
    }

    /// <summary>
    /// 检查文本中是否包含日语特有字符
    /// </summary>
    private static bool ContainsJapanese(string text)
    {
        // 日语平假名和片假名
        return text.Any(c =>
                (c >= 0x3040 && c <= 0x309F) || // 平假名
                (c >= 0x30A0 && c <= 0x30FF)    // 片假名
        );
    }

    /// <summary>
    /// 检查文本中是否包含韩语字符
    /// </summary>
    private static bool ContainsKorean(string text)
    {
        // 韩语谚文
        return text.Any(c => c >= 0xAC00 && c <= 0xD7AF);
    }

    /// <summary>
    /// 检查文本中是否包含西里尔字母(俄语、乌克兰语等)
    /// </summary>
    private static bool ContainsCyrillic(string text)
    {
        // 西里尔字母范围
        return text.Any(c => c >= 0x0400 && c <= 0x04FF);
    }

    /// <summary>
    /// 检查文本中是否包含阿拉伯字符
    /// </summary>
    private static bool ContainsArabic(string text)
    {
        // 阿拉伯字符范围
        return text.Any(c => c >= 0x0600 && c <= 0x06FF);
    }

    /// <summary>
    /// 检查文本中是否包含德文纳格里字符(印地语等)
    /// </summary>
    private static bool ContainsDevanagari(string text)
    {
        // 德文纳格里字符范围（印地语）
        return text.Any(c => c >= 0x0900 && c <= 0x097F);
    }

    /// <summary>
    /// 检查文本中是否包含泰语字符
    /// </summary>
    private static bool ContainsThai(string text)
    {
        // 泰语字符范围
        return text.Any(c => c >= 0x0E00 && c <= 0x0E7F);
    }

    /// <summary>
    /// 检查文本中是否包含波斯语字符
    /// </summary>
    private static bool ContainsPersian(string text)
    {
        // 波斯语使用阿拉伯字符集，但有特定字符
        return ContainsArabic(text) && text.Any(c => c == 0x067E || c == 0x0686 || c == 0x06AF);
    }

    /// <summary>
    /// 计算文本中不同语言特征字符的比例
    /// </summary>
    private static Dictionary<string, double> CalculateLanguageScores(string text)
    {
        if (string.IsNullOrEmpty(text))
            return new Dictionary<string, double>();

        var totalChars = text.Length;
        var scores = new Dictionary<string, double>();

        // 统计不同语言特征字符的数量
        var chineseCount = text.Count(c => c >= 0x4E00 && c <= 0x9FFF);
        var japaneseCount = text.Count(c => (c >= 0x3040 && c <= 0x309F) || (c >= 0x30A0 && c <= 0x30FF));
        var koreanCount = text.Count(c => c >= 0xAC00 && c <= 0xD7AF);
        var cyrillicCount = text.Count(c => c >= 0x0400 && c <= 0x04FF);
        var arabicCount = text.Count(c => c >= 0x0600 && c <= 0x06FF);
        var devanagariCount = text.Count(c => c >= 0x0900 && c <= 0x097F);
        var thaiCount = text.Count(c => c >= 0x0E00 && c <= 0x0E7F);

        // 计算比例
        if (chineseCount > 0) scores["zh"] = (double)chineseCount / totalChars;
        if (japaneseCount > 0) scores["ja"] = (double)japaneseCount / totalChars;
        if (koreanCount > 0) scores["ko"] = (double)koreanCount / totalChars;
        if (cyrillicCount > 0)
        {
            // 区分俄语和乌克兰语 (简化版，实际上需要更复杂的分析)
            if (text.Contains('ї') || text.Contains('є') || text.Contains('і'))
                scores["uk"] = (double)cyrillicCount / totalChars;
            else
                scores["ru"] = (double)cyrillicCount / totalChars;
        }

        if (arabicCount > 0)
        {
            // 区分阿拉伯语和波斯语
            if (text.Any(c => c == 0x067E || c == 0x0686 || c == 0x06AF))
                scores["fa"] = (double)arabicCount / totalChars;
            else
                scores["ar"] = (double)arabicCount / totalChars;
        }

        if (devanagariCount > 0) scores["hi"] = (double)devanagariCount / totalChars;
        if (thaiCount > 0) scores["th"] = (double)thaiCount / totalChars;

        return scores;
    }

    private static int CountSegmentsInSrt(string srtContent)
    {
        if (string.IsNullOrEmpty(srtContent))
            return 0;

        // SRT格式中每个段落由一个数字标识符开始，后面跟着时间码
        // 通过计算数字行（如"1", "2", "3"）的数量来估算段落数
        var lines = srtContent.Split('\n');
        var count = 0;

        for (var i = 0; i < lines.Length; i++)
        {
            if (string.IsNullOrWhiteSpace(lines[i]))
                continue;

            if (int.TryParse(lines[i].Trim(), out _))
                count++;
        }

        return count;
    }

    public class SubtitleResult
    {
        /// <summary>
        /// 生成的字幕文件路径
        /// </summary>
        public string SubtitlePath { get; set; }

        /// <summary>
        /// 检测到的语言
        /// </summary>
        public string DetectedLanguage { get; set; }

        /// <summary>
        /// 字幕片段数量
        /// </summary>
        public int SegmentCount { get; set; }
    }

    public class ProcessProgress
    {
        /// <summary>
        /// 当前处理阶段
        /// </summary>
        public string Stage { get; set; }

        /// <summary>
        /// 进度百分比 (0-100)
        /// </summary>
        public double Percentage { get; set; }

        /// <summary>
        /// 详细信息
        /// </summary>
        public string Details { get; set; }
    }

    public class WhisperOptions
    {
        public WhisperOptions()
        {
            // 根据模型类型设置默认路径
            ModelPath = GetDefaultModelPath(ModelType);
        }

        /// <summary>
        /// 语音识别语言，默认为auto自动检测
        /// </summary>
        public string Language { get; set; } = "auto";

        /// <summary>
        /// 模型类型，默认为Base
        /// </summary>
        public GgmlType ModelType { get; set; } = GgmlType.Base;

        /// <summary>
        /// 模型文件路径，默认位于AppData/WhisperModels目录下
        /// </summary>
        public string ModelPath { get; set; }

        /// <summary>
        /// 是否保留临时WAV文件，默认为false
        /// </summary>
        public bool KeepWavFile { get; set; } = false;

        /// <summary>
        /// 音频采样率，默认16000
        /// </summary>
        public int SampleRate { get; set; } = 16000;

        /// <summary>
        /// 字幕时间戳的最小间隔（毫秒），默认200
        /// </summary>
        public int MinimumSegmentLength { get; set; } = 200;

        /// <summary>
        /// 获取指定模型类型的默认路径
        /// </summary>
        public static string GetDefaultModelPath(GgmlType modelType)
        {
            var fileName = $"ggml-{modelType.ToString().ToLower()}.bin";
            return Path.Combine(Common.GlobalPath, MODEL_FOLDER_NAME, fileName);
        }
    }
}